﻿using System;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using OakEngine.BaseObject;
using OakEngine.AI.Tools;
using OakEngine.AI.State_Machine;
using OakEngine.AI.Behavior_State;
using MainJumpFleet.SteerBehaviors;
using OakEngine.AI.Kinematic;
using OakEngine.AI.Steering;
using OakEngine.Camera;
using System.Collections.Generic;

namespace MainJumpFleet.TempObjects
{
    public class EnemyShip : OAK_BaseGameEntity
    {
        // Temp enemy Texture
        //Texture2D m_enemyTexture;
        // Texture2D m_bulletTexture;
        JumpFleetGameLib.xSprite.StaticSprite enemySprite;
        JumpFleetGameLib.xSprite.StaticSprite bulletSprite;
        bool visible;


        // Tells if this object is alive
        public bool m_bIsAlive;
        public Rectangle Bounds;
        public Rectangle TargetBounds;

        float aggroDistance;
        float shootTimer;

        // State Machine
        Oak_StateMachine<OAK_BaseGameEntity> m_currentState;

        /*********************************
         * AI Section
         *********************************/
        Seek seek;
        SteeringBehavior steeringBehavior;
        Oak_Steering steer;
        Oak_Kinematic agent;
        Oak_Camera camera;

        // Bullets
        List<Bullet> b = new List<Bullet>();

        #region PROPERTIES

        public bool Visible
        {
            get { return visible; }

            set
            {
                visible = value;
                enemySprite.Visible = value;
            }
        }

        public Vector2 Position
        {
            get { return base.Position; }

            set
            {
                base.Position = value;
                enemySprite.DrawPosition = value;
            }
        }

        public float Rotation
        {
            get { return base.Rotation; }

            set
            {
                base.Rotation = value + 1.5f;
                enemySprite.RotationAmount = value + 1.5f;
            }
        }

        #endregion

        public EnemyShip(int id, JumpFleetGameLib.xSprite.StaticSprite enemySprite, JumpFleetGameLib.xSprite.StaticSprite bulletSprite, Vector2 pos, Vector2 target, ref Oak_Camera cam)
            : base(id)
        {
            // m_enemyTexture = tex;
            // m_bulletTexture = bullet;
            this.enemySprite = enemySprite;
            this.bulletSprite = bulletSprite;
            this.Position = pos;
            Bounds = new Rectangle((int)pos.X, (int)pos.Y, enemySprite.Width, enemySprite.Height);
            // Origin = new Vector2(tex.Width * 0.5f, tex.Height * 0.5f);
            Origin = enemySprite.RotationOriginPoint;
            TargetPosition = target;
            WorldBound = new Rectangle(0, 0, 3072, 3072);
            Speed = 1.5f;
            this.Rotation = 0.0f;
            RotationRate = 0.025f;
            m_bIsAlive = true;
            Distance = 100;
            aggroDistance = 350;
            /*******************
             * AI Init
             ********************/
            agent = new Oak_Kinematic();
            agent.Position = Position;
            agent.Direction = new Vector2();
            agent.AngularVelocity = 10;
            agent.Rotation = 0.0f;
            steer = new Oak_Steering();

            seek = new Seek();
            seek.m_Agent = agent;
            seek.m_Target = TargetPosition;
            seek.m_fMaxAcceleration = Speed;
            steeringBehavior = seek;

            camera = cam;



            // For FSM
            //m_currentState = new Oak_StateMachine<OAK_BaseGameEntity>(this);
            //m_currentState.CurrentState = new Oak_WanderBehaviorState();
            //m_currentState.CurrentState.Enter(this);
        }


        public Vector2 GetPosition
        {
            get { return Position; }
        }

        public Vector2 GetVelocity
        {
            get { return Velocity; }
        }

        public void SetTarget(Vector2 tar)
        {
            TargetPosition = tar;
        }
        public void SetTargetBound(ref Rectangle rec)
        {
            TargetBounds = rec;

        }

        public void SetPosition(Vector2 pos)
        {
            Position = pos;
            Bounds = new Rectangle((int)Position.X, (int)Position.Y, enemySprite.Width, enemySprite.Height);

        }



        public override void ChangeState(OakEngine.AI.State_Machine.Oak_IState<OAK_BaseGameEntity> state)
        {
            // m_currentState.ChangeState(state);
        }

        public override void Update(GameTime gameTime)
        {

            //m_currentState.Update();
            float targetDistance = Vector2.Distance(TargetPosition, Position);

            /**************
             ** AI UPDATE
             ***************/
            if (aggroDistance > targetDistance)
            {
                steer.ZeroOut();
                seek.m_Target = TargetPosition;
                steeringBehavior.UpdateSteering(steer);
                agent.Update(steer, 0.95f, (float)gameTime.ElapsedGameTime.TotalSeconds);
                agent.SetRotationFromVelocity();
            }
            if (Distance < targetDistance)
            {
                agent.TrimSpeed(Speed);
            }
            else
                agent.TrimSpeed(0.0f);
            if (500 > targetDistance)
            {
                shootTimer += (float)gameTime.ElapsedGameTime.TotalSeconds;

                if (shootTimer >= 2)
                {
                    Fire(bulletSprite, steer.ForwardVector);
                    shootTimer = 0;
                }
            }

            // check if we move away
            foreach (var bull in b)
            {
                // track the bullet if we are far then reset position and disappear
                if (Vector2.Distance(bull.Position, Position) > 5000 && bull.IsAlive)
                {
                    bull.IsAlive = false;
                    bull.Position = Position;
                    bull.velocity = Vector2.Zero;
                }

                if (bull.IsAlive)
                    bull.Update((float)gameTime.ElapsedGameTime.TotalSeconds);
            }
            Bounds = new Rectangle((int)Position.X, (int)Position.Y, enemySprite.Width, enemySprite.Height);

            Intersect(TargetBounds);

            this.Position = agent.Position;
            this.Rotation = agent.Rotation;
            Bounds = new Rectangle((int)Position.X, (int)Position.Y, enemySprite.Width, enemySprite.Height);

        }

        public override void Render(SpriteBatch batch, ref Oak_Camera cam)
        {
            foreach (var bull in b)
            {
                if (bull.IsAlive)
                    bull.Render(batch);
            }
            // batch.Draw(m_enemyTexture, Position - cam.CameraPosition, null, Color.White, Rotation + 1.5f, Origin, 1, SpriteEffects.None, 0.5f);
        }




        // Bullet stuff

        public bool Intersect(Rectangle rect)
        {
            foreach (var bull in b)
            {
                if (bull.Bounds.Intersects(rect))
                {
                    bull.IsAlive = false;
                }
            }
            return false;
        }


        public void Fire(JumpFleetGameLib.xSprite.StaticSprite bulletSprite, Vector2 direction)
        {


            // first check if we have one that isnt alive and if we do have one then lets use it
            foreach (var bul in b)
            {
                if (!bul.IsAlive)
                {
                    bul.Position = Position;
                    bul.velocity = direction;
                    bul.IsAlive = true;
                    bul.Rotation = Rotation;
                    return;
                }
            }

            // if we dont have any to reuse then we should make a new one
            Bullet bull = new Bullet(bulletSprite, Position, direction, Rotation, ref camera);
            b.Add(bull);
        }


    }
}
